package com.shenjialin.Game;

import com.shenjialin.Map.GameMap;
import com.shenjialin.Map.MapTile;
import com.shenjialin.Tank.EnemyTank;
import com.shenjialin.Tank.MyTank;
import com.shenjialin.Tank.Tank;
import com.shenjialin.util.Constant;
import com.shenjialin.util.MyUtil;
import com.shenjialin.util.MyUtil.*;

import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

import static com.shenjialin.util.Constant.*;
/**
 * 游戏的主窗口类
 * 所有的游戏内容展示都要在该窗口实现
 */
public class GameFrame extends Frame implements Runnable{

    // 第一次使用的时候 进行加载
    private Image overImg = null;
    // 定义一章和屏幕大小一致的图片
    private BufferedImage bufImg = new BufferedImage(FRAME_WIDTH, FRAME_HEIGHT, BufferedImage.TYPE_4BYTE_ABGR);
    // 游戏状态
    private static int gameState;
    // 菜单指向
    private int menuIndex;

    public static int titleBarH;
    // 定义坦克对象
    private MyTank myTank;

    // 敌人坦克的容器
    private List<EnemyTank> enemies = new ArrayList<EnemyTank>();

    // 定义一个地图对象
    private GameMap gameMap;

    /**
     * 对窗口进行初始化
     */
    public GameFrame() {
        initFrame();
        initEventListener();
        // 启动用于刷新窗口的线程
        new Thread(this).start();
    }

    public static int getGameState() {
        return gameState;
    }

    public static void setGameState(int gameState) {
        GameFrame.gameState = gameState;
    }

    /**
     * 绘制；游戏结束的方法
     */


    /**
     * 对游戏进行初始化
     */
    private void initGame(){
        gameState = STATE_MENU;
    }

    /**
     * 属性进行初始化
     */
    private void initFrame(){
        setTitle(GAME_TITLE);

        // 设置窗口大小 700 700
        setSize(FRAME_WIDTH,FRAME_HEIGHT);
        // 设置窗口左上角坐标

        setLocation(FRAME_X,FRAME_Y);

        // 设置窗口大小不会变化
        setResizable(false);
        // 设置窗口可见
        setVisible(true);

        // 求标题栏的高度
        titleBarH = getInsets().top;
        //repaint();
    }



    /**
     * 是Frame类的 方法 继承的方法
     * 该方法负责了所有的绘制的内容、
     * 所有显示的内容 都要在该方法内进行调用 、
     * 该方法不能主动调用
     * 必须通过repaint();去回调该方法
     * @param g1 the specified Graphics window
     */
    public void update(Graphics g1){
        // 得到图片的画笔
        Graphics g = bufImg.getGraphics();
        g.setFont(GAME_FONT);
        switch (gameState){
            case STATE_MENU:
                drawMenu(g);
                break;
            case STATE_HELP:
                drawHelp(g);
                break;
            case STATE_ABOUT:
                drawAbout(g);
                break;
            case STATE_RUN:
                drawRun(g);
                break;
            case STATE_OVER:
                drawOver(g);
                break;
        }
        // 使用系统画笔 将图片绘制到frame
        g1.drawImage(bufImg,0,0,null);
    }

    /**
     * 绘制游戏结束的方法
     * @param g
     */
    private void drawOver(Graphics g) {
        // 保证只加载一次
        if (overImg == null) {
            overImg = MyUtil.createImage("res/over.jpg");
        }

        int imgW = overImg.getWidth(null);
        int imgH = overImg.getHeight(null);


        g.drawImage(overImg, FRAME_WIDTH - imgW >> 1, FRAME_HEIGHT - imgH >> 1, null);
        // 添加按键提示信息
        g.setColor(Color.WHITE);
        g.drawString(OVER_STR0,20,FRAME_HEIGHT - 40);
        g.drawString(OVER_STR1,FRAME_WIDTH  - 250,FRAME_HEIGHT - 40);
    }

    private void drawRun(Graphics g) {
        // 绘制黑色的背景
        g.setColor(Color.BLACK);
        g.fillRect(0,0,FRAME_WIDTH,FRAME_HEIGHT);

        gameMap.draw(g);
        //
        drawEnemies(g);

        myTank.draw(g);

        drawExplodes(g);
        // 子弹和坦克的碰撞的方法
        bulletCollideTank();

        //子弹和所有地图块的碰撞
        bulletCollideMapTile();
    }

    //绘制所有的敌人 如果 敌人已经死亡 从容器中移除
    private void drawEnemies(Graphics g) {
        for (int i = 0; i < enemies.size(); i++) {
            EnemyTank enemy = enemies.get(i);
            if(enemy.isDie()) {
                enemies.remove(i);
                i--;
                continue;
            }
            enemy.draw(g);
        }
    }

    private void drawAbout(Graphics g) {
        
    }

    private void drawHelp(Graphics g) {
        
    }

    /**
     * 绘制菜单状态下的内容
     * @param g 画笔对象 系统提供
     */
    private void drawMenu(Graphics g){
        // 绘制黑色的背景
        g.setColor(Color.BLACK);
        g.fillRect(0,0,FRAME_WIDTH,FRAME_HEIGHT);

        final int STR_WIDTH = 50;
        int x = FRAME_WIDTH - STR_WIDTH>>1;
        int y = FRAME_HEIGHT / 3;
        // 行间距
        final int DIS = 50;
        g.setColor(Color.WHITE);
        for (int i = 0; i < MENUS.length; i++) {// 选中菜单项的颜色变为红色
            if (i == menuIndex) {
                g.setColor(Color.RED);
            } else {// 其他为白色
                g.setColor(Color.WHITE);
            }
            g.drawString(MENUS[i],x,y+DIS*i);
        }

    }

    /**
     * 初始化窗口的时间监听
     */
    private void initEventListener() {
        //注册监听 事件
        addWindowListener(new WindowListener() {
            @Override
            public void windowOpened(WindowEvent e) {

            }

            // 点击关闭按钮的时候 方法会被自动调用
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }

            @Override
            public void windowClosed(WindowEvent e) {

            }

            @Override
            public void windowIconified(WindowEvent e) {

            }

            @Override
            public void windowDeiconified(WindowEvent e) {

            }

            @Override
            public void windowActivated(WindowEvent e) {

            }

            @Override
            public void windowDeactivated(WindowEvent e) {

            }
        });

        // 添加按键监听事件
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyTyped(KeyEvent e) {
                super.keyTyped(e);
            }

            /**
             * 按键按下的时候回调的方法
             * @param e the event to be processed
             */
            @Override
            public void keyPressed(KeyEvent e) {
                // 被按下键的键值
                int keyCode = e.getKeyCode();
                // 不同的游戏状态中 有不同的处理方法
                switch (gameState){
                    case STATE_MENU:
                        keyPressEventMenu(keyCode);
                        break;
                    case STATE_HELP:
                        keyPressEventHelp(keyCode);
                        break;
                    case STATE_ABOUT:
                        keyPressEventAbout(keyCode);
                        break;
                    case STATE_RUN:
                        keyPressEventRun(keyCode);
                        break;
                    case STATE_OVER:
                        keyPressEventOver(keyCode);
                        break;
                }
            }


            /**
             * 按键松开的时候回调的内容
             * @param e the event to be processed
             */
            @Override
            public void keyReleased(KeyEvent e) {
                int keyCode = e.getKeyCode();

                if (gameState == STATE_RUN) {
                    keyReleaseEventRun(keyCode);
                }
            }
        });
    }

    // 按键松开时 游戏中 的处理方法
    private void keyReleaseEventRun(int keyCode) {
        switch (keyCode) {
            case KeyEvent.VK_UP:
            case KeyEvent.VK_W:

            case KeyEvent.VK_DOWN:
            case KeyEvent.VK_S:

            case KeyEvent.VK_LEFT:
            case KeyEvent.VK_A:

            case KeyEvent.VK_RIGHT:
            case KeyEvent.VK_D:
                myTank.setState(Tank.STATE_STAND);
                break;
        }
    }

    /**
     * 游戏结束 的按键处理 TODO
     * @param keyCode
     */
    private void keyPressEventOver(int keyCode) {
        // 结束游戏
        if (keyCode == KeyEvent.VK_ESCAPE) {
            System.exit(0);
        } else if(keyCode == KeyEvent.VK_ENTER) {
            setGameState(STATE_MENU);
            //游戏的很多属性需要 重置
            resetGame();
        }
    }

    // 重置游戏状态
    private void resetGame() {
        menuIndex = 0;
        // 先让自己的坦克子弹 换回对象池
        myTank.bulletsReturn();

        // 销毁自己的坦克
        myTank = null;
        for (EnemyTank enemy : enemies) {
            enemy.bulletsReturn();
        }
        enemies.clear();
        gameMap.tilesReturn();
        //清空敌人坦克的列表

        // 清空地图资源
        gameMap = null;
    }

    /**
     * 游戏运行中 按键处理
     * @param keyCode
     */
    private void keyPressEventRun(int keyCode) {
        switch (keyCode) {
            case KeyEvent.VK_UP:
            case KeyEvent.VK_W:
                myTank.setDir(Tank.DIR_UP);
                myTank.setState(Tank.STATE_MOVE);
                break;
            case KeyEvent.VK_DOWN:
            case KeyEvent.VK_S:
                myTank.setDir(Tank.DIR_DOWN);
                myTank.setState(Tank.STATE_MOVE);
                break;
            case KeyEvent.VK_LEFT:
            case KeyEvent.VK_A:
                myTank.setDir(Tank.DIR_LEFT);
                myTank.setState(Tank.STATE_MOVE);
                break;
            case KeyEvent.VK_RIGHT:
            case KeyEvent.VK_D:
                myTank.setDir(Tank.DIR_RIGHT);
                myTank.setState(Tank.STATE_MOVE);
                break;
            case KeyEvent.VK_SPACE:
                myTank.fire();
                break;
        }
    }

    private void keyPressEventAbout(int keyCode) {

    }

    private void keyPressEventHelp(int keyCode) {

    }

    // 菜单状态下的 按键处理
    private void keyPressEventMenu(int keyCode) {
        switch (keyCode) {
            case KeyEvent.VK_UP:
            case KeyEvent.VK_W:
                menuIndex--;
                if (menuIndex < 0) {
                    menuIndex = MENUS.length - 1;
                }
                //repaint();
                break;
            case KeyEvent.VK_DOWN:
            case KeyEvent.VK_S:
                if (++menuIndex > MENUS.length -1) {
                    menuIndex = 0;
                }
                //repaint();
                break;
            case KeyEvent.VK_ENTER:
                //TODO:启动游戏
                newGame();
                break;

        }
    }

    /**
     * 开始新游戏的方法
     */
    private void newGame() {
        gameState = STATE_RUN;
        // 创建坦克对象 敌人坦克对象
        myTank = new MyTank(DEFAULT_X,DEFAULT_Y,Tank.DIR_DOWN);

        gameMap = new GameMap();
        // 使用一个单独的线程  用于控制 生产敌人的坦克
        new Thread(){// 匿名内部类
            public void run() {
                while (true) {
                    // 每隔5ms 生成一个坦克
                    if (gameState != STATE_RUN) {
                        break;
                    }
                    if(enemies.size() < ENEMY_MAX_COUNT){
                        EnemyTank enemy = EnemyTank.createEnemy();
                        enemies.add(enemy);
                    }
                    try {
                        Thread.sleep(ENEMY_BORN_INTERVAL);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                }
            }
        }.start();
    }

    @Override
    public void run() {
        while (true) {
            // 再次调用 repaint, 回调update
            repaint();
            try {
                Thread.sleep(REPAINT_INTERVAL);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    // 敌人坦克的子弹和我的坦克的碰撞

    private void bulletCollideTank() {
        // 我的坦克和所有敌人的碰撞
        for (EnemyTank enemy : enemies) {
            enemy.collideBullets(myTank.getBullets());
        }

        for (EnemyTank enemy : enemies) {
            myTank.collideBullets(enemy.getBullets());
        }
        // 清理所有被销毁的地图快

        gameMap.clearDestoryTile();
    }

    // 所有的子弹和地图块的碰撞
    private void bulletCollideMapTile() {
        // 自己的坦克的子弹和地图快的碰撞
        myTank.bulletsCollideMapTiles(gameMap.getTiles());
        for (EnemyTank enemy : enemies) {
            enemy.bulletsCollideMapTiles(gameMap.getTiles());
            if(enemy.isCollideTile(gameMap.getTiles())) {
                enemy.back();
            }
        }
        if(myTank.isCollideTile(gameMap.getTiles())) {
            myTank.back();
        }
        //

        // 清除所有被销毁的地图块
        gameMap.clearDestoryTile();
    }


    private void drawExplodes(Graphics g) {
        for (EnemyTank enemy : enemies) {
            enemy.drawExplodes(g);
        }
        myTank.drawExplodes(g);
    }
}
